Ctrl + Alt + I - форматирование кода
python -m pip install Django
python manage.py startapp news
python manage.py runserver
pip install Pillow
pip install django-debug-toolbar
pip install django-ckeditor
pip install django-simple-captcha
python manage.py makemigrations
python manage.py sqlmigrate news 0001
python manage.py migrate Добавляем в БД таблицу из models.py

python manage.py shell Запуск консоли в django
В консоли пишем следующее
from news.models import News

Выход из консоли django
exit()

Заполняем конструктор данными
News(title='Новость 1', content='Контент новости 1')

Сохраняем данные в БД
#1 вариант добавления записи
news1 = _  где _ это предыдущий результат, который сохраняем в переменную
news1.save()
#2 вариант добавления записи
news2 = News(title='Новость 2', content='Контент новости 2')
news2.save()
#3 вариант добавления записи
news3 = News()
news3.title = 'Новость 3'
news3.content='Контент новости 3'
news3.save()
#4 вариант добавления записи
news4 = News.objects.create(title='Новость 4', content='Контент новости 4') Метод save() вызывать не нужно

Проверить действительно ли пустая строка у photo
from django.db import connection
connection.queries

Обращение к первичному ключу
news1.pk

Вернет все записи (объекты) в django
News.objects.all()
news = _
for item in news:
    print(item.title, item.is_published)

News.objects.create(title='News 5', content='Content news 5')

=== FILTER ===
News.objects.filter(title='News 5')

=== GET ===
Получение одной уникальной записи и лучше это делать по uniq значению (pk), иначе будет Exception
News.objects get(pk=5)
News.objects get(title='News 5')

=== UPDATE ===
news4 = _
news4.title = 'Новость есть 4'
news4.save()

=== DELETE ===
news5 = News.objects.get(pk=5)
news5.delete()

=== Сортировка ===
News.objects.order_by('title') сортируем по полю title в алфавитном порядке
News.objects.order_by('-title') в обратном порядке сортировка

=== EXCLUDE ===
News.objects.exclude(title='News 5') Выборка записей за исключением записей, прописанных в условии

=== Admin ===
Создание админа
python manage.py createsuperuser
Имя пользователя: admin
Адрес электронной почты: budaev.e@gmail.com
Password: admin

=== Static ===
python manage.py collectstatic


=== ORM. Часть 1 ===
python manage.py shell
from news.models import News, Category
News.objects.all() получение всех записей
News.objects.order_by('-pk') сортировка по полю
News.objects.all().reverse() изменяем порядок вывода
News.objects.get(pk=1) получение одной записи
news5 = _ последний результат выборки присваиваем в переменную
news5.is_published смотрим опубликована новость или нет
news5.category
news5.category.pk
news5.category.title
cat4 = Category.objects.get(pk=4)
cat4.title
<имя связанной модели>_set
cat4.news_set.all()
news = _
for item in news:
    print(item.title, item.is_published)
cat2 = Category.objects.get(pk=2)
news = cat2.news_set.all()
news
# в models для category добавлен атрибут related_name='get_news'
cat2 = Category.objects.get(pk=2)
news = cat2.get_news.all()

=== ORM. Часть 2 ===
# Фильтры полей Field lookups
<имя поля>__<фильтр>
# gt больше чем
News.objects.filter(pk__gt=12) # больше 12
# gte больше или равно чем
# lt, lte # меньше, меньше или равно
# contains # ищет включения SELECT... WHERE headline LIKE '%Lennon%';
# icontains # регистро-независимый поиск
News.objects.filter(title__contains='new')
# in # диапозон SELECT... WHERE id IN (1,3,4);
News.objects.filter(pk__in=[9, 10, 11])
News.objects.filter(pk__in=[9, 10, 11], title__contains='формы')


=== ORM. Часть 3 ===
News.objects.first() # первый элемент по дате создания в нашем случае
News.objects.order_by('pk').first() # первый элемент в обратном порядке
News.objects.order_by('-pk').first()

cat1 = Category.objects.get(pk=1)
news = cat1.news_set.all()
news = cat1.news_set.filter(pk__gt=1) # pk должен быть больше чем 1
news
news = cat1.news_set.filter(pk__gt=1).first()
news
News.objects.last() # противоположный метод

News.objects.earliest('updated_at')
News.objects.latest('updated_at')

cats = Category.objects.filter(pk__in=[1, 3])
cats # Получили 2 категории
News.objects.filter(category__in=cats) # получаем все записи в этих 2-х категориях

# Количество записей в наборе. Есть или нет записей в наборе
cat1 = Category.objects.get(pk=1)
cat5 = Category.objects.get(pk=5)
cat1.news_set.exists() # True - если есть записи. False - если нет записей в категории
cat5.news_set.exists() # True - если есть записи. False - если нет записей в категории
cat1.news_set.count() # Количество записей
News.objects.count() # Общее количество записей

# Ссылки на предыдущую и следующую статью. Методы работают, если в models есть поле dateField или dateTimeField
news = News.objects.get(pk=5)
news.get_previous_by_created_at() # Получаем предыдущую новость от текущей записи
news.get_next_by_created_at() # Получаем слудующую новость от текущей записи
news.get_next_by_created_at(pk__gt=10, title__contains=7) # pk больше чем 10


=== ORM. Часть 4. Фильтрация по значениям полей и связанных записей ===
# Получение всех записей по title
<имя поля внешнего ключа>__<имя поля первичной модели>
News.objects.filter(category__title='Политика) # все новости из категории Политика

Category.objects.filter(news__title__contains='формы') # отфильтрованный список категорий, у которых новости title содержат слово 'формы' [<Category: Политика>, <Category: Спорт>, <Category: Политика>, <Category: Спорт> ]
Category.objects.filter(news__title__contains='формы').count()
Category.objects.filter(news__title__contains='формы').distinct() # получение уникальных категорий [<Category: Политика>, <Category: Спорт>]

# Логическое И, ИЛИ, НЕ
| логическое ИЛИ
& логическое И
~ логическое НЕ
from django.db.models import Q
News.objects.filter(pk__in=[5, 6], title__contains='2') # здесь логическое И
News.objects.filter(Q(pk__in=[5, 6]) | Q(title__contains='2')) # здесь логическое ИЛИ [<News: Новость из формы 2>, <News: News 5>, <News: Новость 2>]
News.objects.filter(Q(pk__in=[5, 6]) | Q(title__contains='2') & ~ Q(pk__lt=4)) # id 5,6 или title содержит 2 и id должен быть не меньше чем 4


=== ORM. Часть 5. Лимитировать количество записей. Агрегатные функции ===
python manage.py shell  # запуск консоли django
exit()  # выход из консоли django
from news.models import *
News.objects.all()  # все записи [<News: Новость из формы 9>, <News: Новость из формы 8>, и так далее]
News.objects.all()[:3] # Получение первых трех записей
News.objects.all()[10:] # Получение всех записей после 10-ой
News.objects.all()[3:5] # Получение всех записей после третей записи до пятой включительно

# Агрегатные функции (min, max, sum, count, average)
from django.db.models import *
News.objects.aggregate(Min('views'), Max('views'))  # {'views__min': 0, 'views__max': 1000}
News.objects.aggregate(min_views=Min('views'), max_views=Max('views'))  # {'min_views': 0, 'max_views': 1000}
News.objects.aggregate(diff=Min('views') -Max('views')) # разница {'diff': -1000}
News.objects.aggregate(Sum('views'))
News.objects.aggregate(Avg('views')) # среднее
News.objects.aggregate(Count('views'))


=== ORM. Часть 6. Вычисления по группам записей ===
from django.db.models import *
cats = Category.objects.annotate(Count('news')) # получаем категории и вычисляем количество записей по группам
for item in cats:
    print(item.title, item.news__count)
    # Культура 3
    # Наука 1
    # ...

# Используем именованный параметр
cats = Category.objects.annotate(cnt=Count('news'))
for item in cats:
    print(item.title, item.cnt)

# Для каждой рубрики найдем максимальное количество просмотров
cats = Category.objects.annotate(max_views=Max('news__views'))
for item in cats:
    print(item.title, item.max_views)
    # Культура 153
    # Наука 1
    # ...

# Сумма просмотров для каждой категории
cats = Category.objects.annotate(sum_views=Max('news__views'))
for item in cats:
    print(item.title, item.sum_views)
    # Культура 262
    # Наука 1
    # ...

# Убираем категорию в которой нет записей
cats = Category.objects.annotate(cnt=Count('news')).filter(cnt__gt=0)
for item in cats:
    print(item.title, item.cnt) # Увидим только те категории, где есть записи

News.objects.aggregate(cnt=Count('views')) # {'cnt': 15}
# Посчитать уникальные значения
News.objects.aggregate(cnt=Count('views', distinct=True)) # {'cnt': 12}


=== ORM. Часть 7. Метод values(). Класс F  ===
news1 = News.objects.values('title', 'views').get(pk=1)
news1['title'] # 'Новость 1'

from django.db import connection
news = News.objects.values('title', 'views', 'category__title')
connection.queries # выполненные запросы
from django.db import reset_queries
connection.queries # теперь очистили список
for item in news:
    print(item['title'], item['category__title'])

# Класс F
from django.db.models import F

# не рекомендуемое решение
# news1 = News.objects.get(pk=1)
# news1.views += 1
# news1.save()

# используют класс F
news = News.objects.get(pk=1)
news.views = F('views') + 1
news.save()

# Достать новость, которая содержится в контенте
News.objects.filter(content__icontains=F('title')) # [<News: News 5>]

# Функции СУБД
from django.db.models.unctions import Length
news = News.objects.annotate(length=Length('title')).all()
for item in news:
    print(item.title, item.length)


=== ORM. Часть 8. RAW SQL ===
python manage.py shell
from news.models import *
News.objects.raw("SELECT * FROM news_news")
new = _  #  предыдущий запрос сохраняем в переменную
for item in news:
    print(item.title, item.pk, item.is_published)

# отложенная загрузка полей. Не самая лучшая практика
news = News.objects.raw("SELECT id, title FROM news_news")  # обязательное поле id
for item in news:
    print(item.title)

# Выбор по условию
news = News.objects.raw("SELECT * FROM news_news WHERE title = 'News 5'")
for item in news:
   print(item.title)

# Выбор по условию в соответствии с параметром. Безопасный способ.
news = News.objects.raw("SELECT * FROM news_news WHERE title = %s", ['News 5'])
for item in news:
   print(item.title)


=== Django Debug Toolbar ===
pip install django-debug-toolbar


=== django-ckeditor ===
pip install django-ckeditor
python manage.py collectstatic


=== Captcha ===
# в случае возникновения ошибки
pip uninstall captcha
pip uninstall django-simple-captcha
pip install django-simple-captcha
python manage.py migrate



